Micron Document
🎖️GitЯра🎖️


Displaying Raw • Download

core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/viewmodel/UIViewModel.kt e330442dd5415dc7eb2bff4e3a3f1599c18022a1 (e330442d) Text, 16.18 KB

T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.core.ui.viewmodel

Tff7b72import T7ee787androidx.lifecycle.ViewModel
Tff7b72import T7ee787androidx.lifecycle.viewModelScope
Tff7b72import T7ee787androidx.navigation3.runtime.NavKey
Tff7b72import T7ee787co.touchlab.kermit.Logger
Tff7b72import T7ee787kotlinx.coroutines.ExperimentalCoroutinesApi
Tff7b72import T7ee787kotlinx.coroutines.channels.BufferOverflow
Tff7b72import T7ee787kotlinx.coroutines.flow.Flow
Tff7b72import T7ee787kotlinx.coroutines.flow.MutableSharedFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.MutableStateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.StateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.asFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.asSharedFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.asStateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.combine
Tff7b72import T7ee787kotlinx.coroutines.flow.distinctUntilChanged
Tff7b72import T7ee787kotlinx.coroutines.flow.filterNotNull
Tff7b72import T7ee787kotlinx.coroutines.flow.flatMapLatest
Tff7b72import T7ee787kotlinx.coroutines.flow.flowOf
Tff7b72import T7ee787kotlinx.coroutines.flow.launchIn
Tff7b72import T7ee787kotlinx.coroutines.flow.map
Tff7b72import T7ee787kotlinx.coroutines.flow.mapNotNull
Tff7b72import T7ee787kotlinx.coroutines.flow.onEach
Tff7b72import T7ee787org.jetbrains.compose.resources.StringResource
Tff7b72import T7ee787org.jetbrains.compose.resources.getString
Tff7b72import T7ee787org.koin.core.annotation.KoinViewModel
Tff7b72import T7ee787org.meshtastic.core.common.util.CommonUri
Tff7b72import T7ee787org.meshtastic.core.database.entity.asDeviceVersion
Tff7b72import T7ee787org.meshtastic.core.model.ConnectionState
Tff7b72import T7ee787org.meshtastic.core.model.EventFirmwareEdition
Tff7b72import T7ee787org.meshtastic.core.model.MeshActivity
Tff7b72import T7ee787org.meshtastic.core.model.MyNodeInfo
Tff7b72import T7ee787org.meshtastic.core.model.TracerouteMapAvailability
Tff7b72import T7ee787org.meshtastic.core.model.evaluateTracerouteMapAvailability
Tff7b72import T7ee787org.meshtastic.core.model.service.TracerouteResponse
Tff7b72import T7ee787org.meshtastic.core.model.util.dispatchMeshtasticUri
Tff7b72import T7ee787org.meshtastic.core.model.util.isOtaStatusNotification
Tff7b72import T7ee787org.meshtastic.core.navigation.DeepLinkRouter
Tff7b72import T7ee787org.meshtastic.core.repository.EventFirmwareRepository
Tff7b72import T7ee787org.meshtastic.core.repository.FirmwareReleaseRepository
Tff7b72import T7ee787org.meshtastic.core.repository.FirmwareUpdateStatusRepository
Tff7b72import T7ee787org.meshtastic.core.repository.LockdownCoordinator
Tff7b72import T7ee787org.meshtastic.core.repository.LockdownPassphraseStore
Tff7b72import T7ee787org.meshtastic.core.repository.MeshLogRepository
Tff7b72import T7ee787org.meshtastic.core.repository.NodeRepository
Tff7b72import T7ee787org.meshtastic.core.repository.NodeRestartTracker
Tff7b72import T7ee787org.meshtastic.core.repository.NotificationManager
Tff7b72import T7ee787org.meshtastic.core.repository.PacketRepository
Tff7b72import T7ee787org.meshtastic.core.repository.RadioController
Tff7b72import T7ee787org.meshtastic.core.repository.RadioInterfaceService
Tff7b72import T7ee787org.meshtastic.core.repository.ServiceRepository
Tff7b72import T7ee787org.meshtastic.core.repository.UiPrefs
Tff7b72import T7ee787org.meshtastic.core.resources.Res
Tff7b72import T7ee787org.meshtastic.core.resources.client_notification
Tff7b72import T7ee787org.meshtastic.core.resources.compromised_keys
Tff7b72import T7ee787org.meshtastic.core.ui.component.ScrollToTopEvent
Tff7b72import T7ee787org.meshtastic.core.ui.util.AlertManager
Tff7b72import T7ee787org.meshtastic.core.ui.util.ComposableContent
Tff7b72import T7ee787org.meshtastic.core.ui.util.SnackbarManager
Tff7b72import T7ee787org.meshtastic.proto.ChannelSet
Tff7b72import T7ee787org.meshtastic.proto.ClientNotification
Tff7b72import T7ee787org.meshtastic.proto.SharedContact

T8b949e/**
* Shared base for the application-level ViewModel.
*
* Contains all platform-independent state and actions (themes, alerts, connection state, firmware checks, traceroute,
* shared contacts, channel sets, unread counts, etc.).
*/
Tf0883e@KoinViewModel
Tf0883e@OptInTb4b4b4(Te6edf3ExperimentalCoroutinesApiTff7b72::Te6edf3classTb4b4b4)
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffLongParameterListTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffTooManyFunctionsTa5d6ff"Tb4b4b4)
Tff7b72class T56d364UIViewModelTb4b4b4(
Tff7b72private Tff7b72val Te6edf3nodeDBTb4b4b4: Te6edf3NodeRepositoryTb4b4b4,
Tff7b72protected Tff7b72val Te6edf3serviceRepositoryTb4b4b4: Te6edf3ServiceRepositoryTb4b4b4,
Tff7b72private Tff7b72val Te6edf3radioControllerTb4b4b4: Te6edf3RadioControllerTb4b4b4,
Tff7b72private Tff7b72val Te6edf3lockdownCoordinatorTb4b4b4: Te6edf3LockdownCoordinatorTb4b4b4,
Te6edf3radioInterfaceServiceTb4b4b4: Te6edf3RadioInterfaceServiceTb4b4b4,
Te6edf3meshLogRepositoryTb4b4b4: Te6edf3MeshLogRepositoryTb4b4b4,
Te6edf3firmwareReleaseRepositoryTb4b4b4: Te6edf3FirmwareReleaseRepositoryTb4b4b4,
Tff7b72private Tff7b72val Te6edf3eventFirmwareRepositoryTb4b4b4: Te6edf3EventFirmwareRepositoryTb4b4b4,
Tff7b72private Tff7b72val Te6edf3firmwareUpdateStatusRepositoryTb4b4b4: Te6edf3FirmwareUpdateStatusRepositoryTb4b4b4,
Tff7b72private Tff7b72val Te6edf3uiPrefsTb4b4b4: Te6edf3UiPrefsTb4b4b4,
Tff7b72private Tff7b72val Te6edf3notificationManagerTb4b4b4: Te6edf3NotificationManagerTb4b4b4,
Te6edf3packetRepositoryTb4b4b4: Te6edf3PacketRepositoryTb4b4b4,
Tff7b72val Te6edf3alertManagerTb4b4b4: Te6edf3AlertManagerTb4b4b4,
Tff7b72val Te6edf3snackbarManagerTb4b4b4: Te6edf3SnackbarManagerTb4b4b4,
Te6edf3nodeRestartTrackerTb4b4b4: Te6edf3NodeRestartTrackerTb4b4b4,
Tb4b4b4) Tb4b4b4: Te6edf3ViewModelTb4b4b4(Tb4b4b4) Tb4b4b4{

T8b949e/** True while the connected node is expected to be mid-restart (reboot-applying config save or reboot command). */
Tff7b72val Te6edf3nodeRestartExpectedTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657BooleanTff7b72> Tff7b72= Te6edf3nodeRestartTrackerTb4b4b4.Te6edf3restartExpected

T8b949e/**
* True while the handshake-stall watchdog is force-reconnecting the transport, so the UI can present the transient
* Disconnected window as an in-progress recovery rather than a user-visible disconnect. Same signal contract as
* [ConnectionsViewModel.connectionStatus]'s RECONNECTING case.
*/
Tff7b72val Te6edf3watchdogReconnectInFlightTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657BooleanTff7b72> Tff7b72=
Te6edf3combineTb4b4b4(Te6edf3serviceRepositoryTb4b4b4.Te6edf3connectionStateTb4b4b4, Te6edf3serviceRepositoryTb4b4b4.Te6edf3connectionProgressTb4b4b4) Tb4b4b4{ Te6edf3stateTb4b4b4, Te6edf3progress Tff7b72-Tff7b72>
Te6edf3state Tff7b72is Te6edf3ConnectionStateTb4b4b4.Te6edf3Disconnected Tff7b72&Tff7b72& Te6edf3progress Tff7b72=Tff7b72= Te6edf3ServiceRepositoryTb4b4b4.Te6edf3RECONNECTING_PROGRESS_TEXT
Tb4b4b4}
Tb4b4b4.Te6edf3distinctUntilChangedTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3stateInWhileSubscribedTb4b4b4(Te6edf3initialValue Tff7b72= Tff7b72falseTb4b4b4)

Tff7b72private Tff7b72val Te6edf3_navigationDeepLink Tff7b72= Te6edf3MutableSharedFlowTff7b72<Te6edf3ListTff7b72<Te6edf3NavKeyTff7b72>Tff7b72>Tb4b4b4(Te6edf3replay Tff7b72= T79c0ff1Tb4b4b4)
Tff7b72val Te6edf3navigationDeepLink Tff7b72= Te6edf3_navigationDeepLinkTb4b4b4.Te6edf3asSharedFlowTb4b4b4(Tb4b4b4)

T8b949e/**
* Unified handler for all Meshtastic deep links and OS intents.
*
* This method orchestrates two distinct types of URI handling:
* 1. **Navigation:** First attempts to parse the URI into a typed [NavKey] backstack via [DeepLinkRouter]. If
* successful, navigates the user to the target screen.
* 2. **Data Import:** If navigation fails, falls back to legacy contact/channel parsing via
* [dispatchMeshtasticUri]. This triggers import dialogs for shared nodes or channel configurations.
*/
Tff7b72fun Td2a8ffhandleDeepLinkTb4b4b4(Te6edf3uriTb4b4b4: Te6edf3CommonUriTb4b4b4, Te6edf3onInvalidTb4b4b4: Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657Unit Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4) Tb4b4b4{
T8b949e// Try navigation routing first
Tff7b72val Te6edf3navKeys Tff7b72= Te6edf3DeepLinkRouterTb4b4b4.Te6edf3routeTb4b4b4(Te6edf3uriTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3navKeys Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3_navigationDeepLinkTb4b4b4.Te6edf3tryEmitTb4b4b4(Te6edf3navKeysTb4b4b4)
Tff7b72return
Tb4b4b4}

T8b949e// Fallback to channel/contact importing
Te6edf3uriTb4b4b4.Te6edf3dispatchMeshtasticUriTb4b4b4(
Te6edf3onContact Tff7b72= Tb4b4b4{ Te6edf3setSharedContactRequestedTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}Tb4b4b4,
Te6edf3onChannel Tff7b72= Tb4b4b4{ Te6edf3setRequestChannelSetTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}Tb4b4b4,
Te6edf3onInvalid Tff7b72= Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3w Tb4b4b4{ Ta5d6ff"Ta5d6ffImport URI rejected: Tffd700${Te6edf3uriTb4b4b4.Te6edf3toSanitizedImportSummaryTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff" Tb4b4b4}
Te6edf3onInvalidTb4b4b4(Tb4b4b4)
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tb4b4b4}

Tff7b72val Te6edf3themeTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657IntTff7b72> Tff7b72= Te6edf3uiPrefsTb4b4b4.Te6edf3theme

T8b949e/** Opt-out for applying an event edition's ambient theme (accent + typeface) app-wide. */
Tff7b72val Te6edf3eventThemeEnabledTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657BooleanTff7b72> Tff7b72= Te6edf3uiPrefsTb4b4b4.Te6edf3eventThemeEnabled

Tff7b72fun Td2a8ffsetEventThemeEnabledTb4b4b4(Te6edf3enabledTb4b4b4: Tffa657BooleanTb4b4b4) Tff7b72= Te6edf3uiPrefsTb4b4b4.Te6edf3setEventThemeEnabledTb4b4b4(Te6edf3enabledTb4b4b4)

Tff7b72val Te6edf3firmwareEdition Tff7b72= Te6edf3meshLogRepositoryTb4b4b4.Te6edf3getMyNodeInfoTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3map Tb4b4b4{ Te6edf3nodeInfo Tff7b72-Tff7b72> Te6edf3nodeInfoTff7b72?.Te6edf3firmware_edition Tb4b4b4}

Tff7b72val Te6edf3eventEditionTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3EventFirmwareEdition?Tff7b72> Tff7b72=
Te6edf3combineTb4b4b4(Te6edf3firmwareEditionTb4b4b4, Te6edf3connectionStateTb4b4b4) Tb4b4b4{ Te6edf3editionTb4b4b4, Te6edf3state Tff7b72-Tff7b72>
Te6edf3editionTff7b72?.Te6edf3nameTff7b72?.Te6edf3takeIf Tb4b4b4{ Te6edf3state Tff7b72is Te6edf3ConnectionStateTb4b4b4.Te6edf3Connected Tb4b4b4}
Tb4b4b4}
Tb4b4b4.Te6edf3distinctUntilChangedTb4b4b4(Tb4b4b4)
T8b949e// Observe rather than read once, so a manifest refresh that lands after connecting reaches the branding
T8b949e// already on screen instead of waiting for a reconnect.
Tb4b4b4.Te6edf3flatMapLatest Tb4b4b4{ Te6edf3editionName Tff7b72-Tff7b72>
Te6edf3editionNameTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3eventFirmwareRepositoryTb4b4b4.Te6edf3observeEditionTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4} Tff7b72?: Te6edf3flowOfTb4b4b4(Tff7b72nullTb4b4b4)
Tb4b4b4}
Tb4b4b4.Te6edf3stateInWhileSubscribedTb4b4b4(Te6edf3initialValue Tff7b72= Tff7b72nullTb4b4b4)

Tff7b72val Te6edf3clientNotificationTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3ClientNotification?Tff7b72> Tff7b72= Te6edf3serviceRepositoryTb4b4b4.Te6edf3clientNotification

Tff7b72fun Td2a8ffclearClientNotificationTb4b4b4(Te6edf3notificationTb4b4b4: Te6edf3ClientNotificationTb4b4b4) Tb4b4b4{
Te6edf3serviceRepositoryTb4b4b4.Te6edf3clearClientNotificationTb4b4b4(Tb4b4b4)
Te6edf3notificationManagerTb4b4b4.Te6edf3cancelTb4b4b4(Te6edf3notificationTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3hashCodeTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}

Tff7b72val Te6edf3lockdownState Tff7b72= Te6edf3serviceRepositoryTb4b4b4.Te6edf3lockdownState
Tff7b72val Te6edf3lockdownTokenInfo Tff7b72= Te6edf3serviceRepositoryTb4b4b4.Te6edf3lockdownTokenInfo

Tff7b72fun Td2a8ffsendLockdownUnlockTb4b4b4(
Te6edf3passphraseTb4b4b4: Tffa657StringTb4b4b4,
Te6edf3bootTtlTb4b4b4: Tffa657Int Tff7b72= Te6edf3DEFAULT_BOOT_TTLTb4b4b4,
Te6edf3hourTtlTb4b4b4: Tffa657Int Tff7b72= T79c0ff0Tb4b4b4,
Te6edf3maxSessionSecondsTb4b4b4: Tffa657Int Tff7b72= T79c0ff0Tb4b4b4,
Te6edf3disableTb4b4b4: Tffa657Boolean Tff7b72= Tff7b72falseTb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3lockdownCoordinatorTb4b4b4.Te6edf3submitPassphraseTb4b4b4(Te6edf3passphraseTb4b4b4, Te6edf3bootTtlTb4b4b4, Te6edf3hourTtlTb4b4b4, Te6edf3maxSessionSecondsTb4b4b4, Te6edf3disableTb4b4b4)
Tb4b4b4}

Tff7b72fun Td2a8ffsendLockNowTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3lockdownCoordinatorTb4b4b4.Te6edf3lockNowTb4b4b4(Tb4b4b4)
Tb4b4b4}

Tff7b72fun Td2a8ffclearLockdownStateTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3serviceRepositoryTb4b4b4.Te6edf3clearLockdownStateTb4b4b4(Tb4b4b4)
Tb4b4b4}

T8b949e/** Emits events for mesh network send/receive activity. */
Tff7b72val Te6edf3meshActivityTb4b4b4: Te6edf3FlowTff7b72<Te6edf3MeshActivityTff7b72> Tff7b72= Te6edf3radioInterfaceServiceTb4b4b4.Te6edf3meshActivity

Tff7b72val Te6edf3currentDeviceAddressFlowTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657String?Tff7b72> Tff7b72= Te6edf3radioInterfaceServiceTb4b4b4.Te6edf3currentDeviceAddressFlow

Tff7b72private Tff7b72val Te6edf3_scrollToTopEventFlow Tff7b72=
Te6edf3MutableSharedFlowTff7b72<Te6edf3ScrollToTopEventTff7b72>Tb4b4b4(Te6edf3extraBufferCapacity Tff7b72= T79c0ff1Tb4b4b4, Te6edf3onBufferOverflow Tff7b72= Te6edf3BufferOverflowTb4b4b4.Te6edf3DROP_OLDESTTb4b4b4)
Tff7b72val Te6edf3scrollToTopEventFlowTb4b4b4: Te6edf3FlowTff7b72<Te6edf3ScrollToTopEventTff7b72> Tff7b72= Te6edf3_scrollToTopEventFlowTb4b4b4.Te6edf3asFlowTb4b4b4(Tb4b4b4)

Tff7b72fun Td2a8ffemitScrollToTopEventTb4b4b4(Te6edf3eventTb4b4b4: Te6edf3ScrollToTopEventTb4b4b4) Tb4b4b4{
Te6edf3_scrollToTopEventFlowTb4b4b4.Te6edf3tryEmitTb4b4b4(Te6edf3eventTb4b4b4)
Tb4b4b4}

Tff7b72fun Td2a8fftracerouteMapAvailabilityTb4b4b4(Te6edf3forwardRouteTb4b4b4: Te6edf3ListTff7b72<Tffa657IntTff7b72>Tb4b4b4, Te6edf3returnRouteTb4b4b4: Te6edf3ListTff7b72<Tffa657IntTff7b72>Tb4b4b4)Tb4b4b4: Te6edf3TracerouteMapAvailability Tff7b72=
Te6edf3evaluateTracerouteMapAvailabilityTb4b4b4(
Te6edf3forwardRoute Tff7b72= Te6edf3forwardRouteTb4b4b4,
Te6edf3returnRoute Tff7b72= Te6edf3returnRouteTb4b4b4,
Te6edf3positionedNodeNums Tff7b72=
Te6edf3nodeDBTb4b4b4.Te6edf3nodeDBbyNumTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3valuesTb4b4b4.Te6edf3filter Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3validPosition Tff7b72!Tff7b72= Tff7b72null Tb4b4b4}Tb4b4b4.Te6edf3map Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3num Tb4b4b4}Tb4b4b4.Te6edf3toSetTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4)

Tff7b72fun Td2a8ffshowAlertTb4b4b4(
Te6edf3titleTb4b4b4: Tffa657String? Tff7b72= Tff7b72nullTb4b4b4,
Te6edf3titleResTb4b4b4: Te6edf3StringResource? Tff7b72= Tff7b72nullTb4b4b4,
Te6edf3messageTb4b4b4: Tffa657String? Tff7b72= Tff7b72nullTb4b4b4,
Te6edf3messageResTb4b4b4: Te6edf3StringResource? Tff7b72= Tff7b72nullTb4b4b4,
Te6edf3composableMessageTb4b4b4: Te6edf3ComposableContent? Tff7b72= Tff7b72nullTb4b4b4,
Te6edf3htmlTb4b4b4: Tffa657String? Tff7b72= Tff7b72nullTb4b4b4,
Te6edf3onConfirmTb4b4b4: Tb4b4b4(Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4)Tff7b72? Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4,
Te6edf3onDismissTb4b4b4: Tb4b4b4(Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4)Tff7b72? Tff7b72= Tff7b72nullTb4b4b4,
Te6edf3confirmTextTb4b4b4: Tffa657String? Tff7b72= Tff7b72nullTb4b4b4,
Te6edf3confirmTextResTb4b4b4: Te6edf3StringResource? Tff7b72= Tff7b72nullTb4b4b4,
Te6edf3dismissTextTb4b4b4: Tffa657String? Tff7b72= Tff7b72nullTb4b4b4,
Te6edf3dismissTextResTb4b4b4: Te6edf3StringResource? Tff7b72= Tff7b72nullTb4b4b4,
Te6edf3choicesTb4b4b4: Te6edf3MapTff7b72<Tffa657StringTb4b4b4, Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTff7b72> Tff7b72= Te6edf3emptyMapTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3alertManagerTb4b4b4.Te6edf3showAlertTb4b4b4(
Te6edf3title Tff7b72= Te6edf3titleTb4b4b4,
Te6edf3titleRes Tff7b72= Te6edf3titleResTb4b4b4,
Te6edf3message Tff7b72= Te6edf3messageTb4b4b4,
Te6edf3messageRes Tff7b72= Te6edf3messageResTb4b4b4,
Te6edf3composableMessage Tff7b72= Te6edf3composableMessageTb4b4b4,
Te6edf3html Tff7b72= Te6edf3htmlTb4b4b4,
Te6edf3onConfirm Tff7b72= Te6edf3onConfirmTb4b4b4,
Te6edf3onDismiss Tff7b72= Te6edf3onDismissTb4b4b4,
Te6edf3confirmText Tff7b72= Te6edf3confirmTextTb4b4b4,
Te6edf3confirmTextRes Tff7b72= Te6edf3confirmTextResTb4b4b4,
Te6edf3dismissText Tff7b72= Te6edf3dismissTextTb4b4b4,
Te6edf3dismissTextRes Tff7b72= Te6edf3dismissTextResTb4b4b4,
Te6edf3choices Tff7b72= Te6edf3choicesTb4b4b4,
Tb4b4b4)
Tb4b4b4}

Tff7b72fun Td2a8ffdismissAlertTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3alertManagerTb4b4b4.Te6edf3dismissAlertTb4b4b4(Tb4b4b4)
Tb4b4b4}

Tff7b72fun Td2a8ffshowSnackbarTb4b4b4(Te6edf3messageTb4b4b4: Tffa657StringTb4b4b4, Te6edf3actionLabelTb4b4b4: Tffa657String? Tff7b72= Tff7b72nullTb4b4b4, Te6edf3onActionTb4b4b4: Tb4b4b4(Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4)Tff7b72? Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3snackbarManagerTb4b4b4.Te6edf3showSnackbarTb4b4b4(Te6edf3message Tff7b72= Te6edf3messageTb4b4b4, Te6edf3actionLabel Tff7b72= Te6edf3actionLabelTb4b4b4, Te6edf3onAction Tff7b72= Te6edf3onActionTb4b4b4)
Tb4b4b4}

Tff7b72fun Td2a8ffsetDeviceAddressTb4b4b4(Te6edf3addressTb4b4b4: Tffa657StringTb4b4b4) Tb4b4b4{
Te6edf3safeLaunchTb4b4b4(Te6edf3tag Tff7b72= Ta5d6ff"Ta5d6ffsetDeviceAddressTa5d6ff"Tb4b4b4) Tb4b4b4{ Te6edf3radioControllerTb4b4b4.Te6edf3setDeviceAddressTb4b4b4(Te6edf3addressTb4b4b4) Tb4b4b4}
Tb4b4b4}

Tff7b72val Te6edf3unreadMessageCount Tff7b72=
Te6edf3packetRepositoryTb4b4b4.Te6edf3getUnreadCountTotalTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3map Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3coerceAtLeastTb4b4b4(T79c0ff0Tb4b4b4) Tb4b4b4}Tb4b4b4.Te6edf3stateInWhileSubscribedTb4b4b4(Te6edf3initialValue Tff7b72= T79c0ff0Tb4b4b4)

T8b949e// hardware info about our local device (can be null)
Tff7b72val Te6edf3myNodeInfoTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3MyNodeInfo?Tff7b72>
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3nodeDBTb4b4b4.Te6edf3myNodeInfo

Tff7b72init Tb4b4b4{
Te6edf3serviceRepositoryTb4b4b4.Te6edf3errorMessage
Tb4b4b4.Te6edf3filterNotNullTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3onEach Tb4b4b4{
Te6edf3showAlertTb4b4b4(
Te6edf3titleRes Tff7b72= Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3client_notificationTb4b4b4,
Te6edf3message Tff7b72= Tffa657itTb4b4b4,
Te6edf3onConfirm Tff7b72= Tb4b4b4{ Te6edf3serviceRepositoryTb4b4b4.Te6edf3clearErrorMessageTb4b4b4(Tb4b4b4) Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4.Te6edf3launchInTb4b4b4(Te6edf3viewModelScopeTb4b4b4)

Te6edf3serviceRepositoryTb4b4b4.Te6edf3clientNotification
Tb4b4b4.Te6edf3filterNotNullTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3onEach Tb4b4b4{ Te6edf3notification Tff7b72-Tff7b72>
Tff7b72val Te6edf3firmwareUpdateStatus Tff7b72= Te6edf3firmwareUpdateStatusRepositoryTb4b4b4.Te6edf3statusTb4b4b4.Te6edf3value
Tff7b72if Tb4b4b4(Te6edf3notificationTb4b4b4.Te6edf3isOtaStatusNotificationTb4b4b4(Tb4b4b4) Tff7b72&Tff7b72& Te6edf3firmwareUpdateStatusTb4b4b4.Te6edf3isOtaUpdateActiveTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3i Tb4b4b4{ Ta5d6ff"Ta5d6ffSuppressing OTA status ClientNotification generic alert during firmware updateTa5d6ff" Tb4b4b4}
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3firmwareUpdateStatusTb4b4b4.Te6edf3isAwaitingOtaStatusTb4b4b4) Tb4b4b4{
Te6edf3clearClientNotificationTb4b4b4(Te6edf3notificationTb4b4b4)
Tb4b4b4}
Tff7b72returnTf0883e@onEach
Tb4b4b4}
Tff7b72val Te6edf3isCompromised Tff7b72= Te6edf3notificationTb4b4b4.Te6edf3low_entropy_key Tff7b72!Tff7b72= Tff7b72null Tff7b72|Tff7b72| Te6edf3notificationTb4b4b4.Te6edf3duplicated_public_key Tff7b72!Tff7b72= Tff7b72null
Te6edf3showAlertTb4b4b4(
Te6edf3titleRes Tff7b72= Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3client_notificationTb4b4b4,
Te6edf3message Tff7b72= Tff7b72if Tb4b4b4(Te6edf3isCompromisedTb4b4b4) Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3compromised_keysTb4b4b4) Tff7b72else Te6edf3notificationTb4b4b4.Te6edf3messageTb4b4b4,
Te6edf3onConfirm Tff7b72= Tb4b4b4{
T8b949e// Action for compromised keys should be handled via a callback or event
Te6edf3clearClientNotificationTb4b4b4(Te6edf3notificationTb4b4b4)
Tb4b4b4}Tb4b4b4,
Te6edf3onDismiss Tff7b72= Tb4b4b4{ Te6edf3clearClientNotificationTb4b4b4(Te6edf3notificationTb4b4b4) Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4.Te6edf3launchInTb4b4b4(Te6edf3viewModelScopeTb4b4b4)

Te6edf3LoggerTb4b4b4.Te6edf3d Tb4b4b4{ Ta5d6ff"Ta5d6ffUIViewModel createdTa5d6ff" Tb4b4b4}
Tb4b4b4}

Tff7b72private Tff7b72val Te6edf3_sharedContactRequestedTb4b4b4: Te6edf3MutableStateFlowTff7b72<Te6edf3SharedContact?Tff7b72> Tff7b72= Te6edf3MutableStateFlowTb4b4b4(Tff7b72nullTb4b4b4)
Tff7b72val Te6edf3sharedContactRequestedTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3SharedContact?Tff7b72>
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3_sharedContactRequestedTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)

Tff7b72fun Td2a8ffsetSharedContactRequestedTb4b4b4(Te6edf3contactTb4b4b4: Te6edf3SharedContact?Tb4b4b4) Tb4b4b4{
Te6edf3_sharedContactRequestedTb4b4b4.Te6edf3value Tff7b72= Te6edf3contact
Tb4b4b4}

T8b949e/** Clears the pending shared contact request. */
Tff7b72fun Td2a8ffclearSharedContactRequestedTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3_sharedContactRequestedTb4b4b4.Te6edf3value Tff7b72= Tff7b72null
Tb4b4b4}

T8b949e/** Canonical app-level connection state, sourced from [ServiceRepository.connectionState]. */
Tff7b72val Te6edf3connectionState
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3serviceRepositoryTb4b4b4.Te6edf3connectionState

Tff7b72private Tff7b72val Te6edf3_requestChannelSet Tff7b72= Te6edf3MutableStateFlowTff7b72<Te6edf3ChannelSet?Tff7b72>Tb4b4b4(Tff7b72nullTb4b4b4)
Tff7b72val Te6edf3requestChannelSetTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3ChannelSet?Tff7b72>
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3_requestChannelSet

Tff7b72fun Td2a8ffsetRequestChannelSetTb4b4b4(Te6edf3channelSetTb4b4b4: Te6edf3ChannelSet?Tb4b4b4) Tb4b4b4{
Te6edf3_requestChannelSetTb4b4b4.Te6edf3value Tff7b72= Te6edf3channelSet
Tb4b4b4}

Tff7b72val Te6edf3latestStableFirmwareRelease Tff7b72= Te6edf3firmwareReleaseRepositoryTb4b4b4.Te6edf3stableReleaseTb4b4b4.Te6edf3mapNotNull Tb4b4b4{ Tffa657itTff7b72?.Te6edf3asDeviceVersionTb4b4b4(Tb4b4b4) Tb4b4b4}

T8b949e/** Clears the pending channel set import request. */
Tff7b72fun Td2a8ffclearRequestChannelUrlTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3_requestChannelSetTb4b4b4.Te6edf3value Tff7b72= Tff7b72null
Tb4b4b4}

Tff7b72override Tff7b72fun Td2a8ffonClearedTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72superTb4b4b4.Te6edf3onClearedTb4b4b4(Tb4b4b4)
Te6edf3LoggerTb4b4b4.Te6edf3d Tb4b4b4{ Ta5d6ff"Ta5d6ffUIViewModel clearedTa5d6ff" Tb4b4b4}
Tb4b4b4}

Tff7b72val Te6edf3tracerouteResponseTb4b4b4: Te6edf3FlowTff7b72<Te6edf3TracerouteResponse?Tff7b72>
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3serviceRepositoryTb4b4b4.Te6edf3tracerouteResponse

Tff7b72fun Td2a8ffclearTracerouteResponseTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3serviceRepositoryTb4b4b4.Te6edf3clearTracerouteResponseTb4b4b4(Tb4b4b4)
Tb4b4b4}

Tff7b72val Te6edf3neighborInfoResponseTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657String?Tff7b72> Tff7b72= Te6edf3serviceRepositoryTb4b4b4.Te6edf3neighborInfoResponse

Tff7b72fun Td2a8ffclearNeighborInfoResponseTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3serviceRepositoryTb4b4b4.Te6edf3clearNeighborInfoResponseTb4b4b4(Tb4b4b4)
Tb4b4b4}

Tff7b72val Te6edf3appIntroCompletedTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657BooleanTff7b72> Tff7b72= Te6edf3uiPrefsTb4b4b4.Te6edf3appIntroCompleted

Tff7b72fun Td2a8ffonAppIntroCompletedTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3uiPrefsTb4b4b4.Te6edf3setAppIntroCompletedTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4}

Tff7b72companion Tff7b72object Tb4b4b4{
Tff7b72private Tff7b72const Tff7b72val Te6edf3DEFAULT_BOOT_TTL Tff7b72= Te6edf3LockdownPassphraseStoreTb4b4b4.Te6edf3DEFAULT_BOOTS
Tb4b4b4}
Tb4b4b4}

Tff7b72internal Tff7b72fun Te6edf3CommonUriTb4b4b4.Td2a8fftoSanitizedImportSummaryTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657String Tb4b4b4{
Tff7b72val Te6edf3fragmentLength Tff7b72= Te6edf3fragmentTff7b72?.Te6edf3length Tff7b72?: T79c0ff0
Tff7b72val Te6edf3hasFragment Tff7b72= Tff7b72!Te6edf3fragmentTb4b4b4.Te6edf3isNullOrBlankTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3queryParameterCount Tff7b72= Te6edf3getQueryParameterNamesTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3size
T8b949e// pathSegments values are not logged: a malformed channel URL can still leak structure (e.g.
T8b949e// a malformed "/e/" path). pathSegmentCount is enough to diagnose routing without exposing it.
Tff7b72return Ta5d6ff"Ta5d6ffrawLength=Tffd700${Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3lengthTffd700}Ta5d6ff scheme=Tffd700$Te6edf3schemeTa5d6ff host=Tffd700$Te6edf3hostTa5d6ff Ta5d6ff" Tff7b72+
Ta5d6ff"Ta5d6ffpathSegmentCount=Tffd700${Te6edf3pathSegmentsTb4b4b4.Te6edf3sizeTffd700}Ta5d6ff hasFragment=Tffd700$Te6edf3hasFragmentTa5d6ff Ta5d6ff" Tff7b72+
Ta5d6ff"Ta5d6fffragmentLength=Tffd700$Te6edf3fragmentLengthTa5d6ff queryParameterCount=Tffd700$Te6edf3queryParameterCountTa5d6ff"
Tb4b4b4}

Served by rngit 1.5.0 - Generated in 0.16s